package org.lemon.cla.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.lemon.cla.enums.HttpStatusEnum;
import org.lemon.cla.dto.response.ResponseResult;
import org.lemon.cla.dto.request.ClubCreateRequest;
import org.lemon.cla.dto.request.ClubUpdateRequest;
import org.lemon.cla.dto.request.ClubSearchRequest;
import org.lemon.cla.pojo.Club;
import org.lemon.cla.pojo.User;
import org.lemon.cla.vo.ClubVo;
import org.lemon.cla.enums.ClubStatusEnum;
import org.lemon.cla.service.IClubService;
import org.lemon.cla.service.IUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;

import java.time.LocalDateTime;
import java.util.Optional; // 导入 Optional

import org.lemon.cla.exception.BusinessException; // 导入自定义业务异常


@RestController
@RequestMapping("/api/clubs")
@Tag(name = "社团管理", description = "提供社团信息的 CRUD 和查询接口")
public class ClubController {

    @Autowired
    private IClubService clubService;

    @Autowired
    private IUserService userService;

    @Operation(summary = "分页查询社团", description = "根据条件分页获取社团列表。查询条件通过请求体传递，**返回包含创建人信息 (若创建人被逻辑删除则显示为未知)**。")
    @PostMapping("/search")
    public ResponseResult<IPage<ClubVo>> searchClubs(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页数量", example = "10") @RequestParam(defaultValue = "10") Integer pageSize,
            @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "社团查询请求对象 (可选，用于筛选)",
                    required = false,
                    content = @Content(schema = @Schema(implementation = ClubSearchRequest.class))
            ) @org.springframework.web.bind.annotation.RequestBody ClubSearchRequest request) {

        Page<ClubVo> page = new Page<>(pageNum, pageSize);

        // 使用Optional简化，确保request总是一个非null的实例
        request = Optional.ofNullable(request).orElseGet(ClubSearchRequest::new);

        IPage<ClubVo> clubPage = clubService.searchClubsByConditions(page, request);
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), clubPage);
    }


    @Operation(summary = "获取所有社团", description = "分页获取所有社团列表（不带任何筛选条件），**包含创建人信息 (若创建人被逻辑删除则显示为未知)**")
    @GetMapping
    public ResponseResult<IPage<ClubVo>> getAllClubs(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页数量", example = "10") @RequestParam(defaultValue = "10") Integer pageSize) {
        Page<ClubVo> page = new Page<>(pageNum, pageSize);
        // 调用统一的搜索方法，传入空的请求对象，表示无筛选
        IPage<ClubVo> clubPage = clubService.searchClubsByConditions(page, new ClubSearchRequest());
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), clubPage);
    }

    @Operation(summary = "根据ID获取社团", description = "根据社团ID获取社团详情，**包含创建人信息 (若创建人被逻辑删除则显示为未知)**")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功获取社团"),
            @ApiResponse(responseCode = "404", description = "社团未找到")
    })
    @GetMapping("/{id}")
    public ResponseResult<ClubVo> getClubById(
            @Parameter(description = "社团ID", required = true, example = "1") @PathVariable Long id) {
        // 使用Optional简化null检查，如果未找到则抛出业务异常
        return Optional.ofNullable(clubService.getClubVoById(id))
                .map(clubVo -> ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), clubVo))
                .orElseThrow(() -> new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "社团未找到。")); // 抛出业务异常
    }

    @Operation(summary = "创建新社团", description = "创建一个新的社团记录 (**创建人不能是逻辑删除状态**)")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "201", description = "社团创建成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误 (如校验失败)"),
            @ApiResponse(responseCode = "404", description = "创建人用户不存在或已逻辑删除"),
            @ApiResponse(responseCode = "409", description = "社团名称已存在"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping
    @PreAuthorize("hasRole('管理员')")
    public ResponseResult<Club> createClub(
            @Parameter(description = "社团创建请求对象 (无需传入 clubId, createTime, status)", required = true)
            @RequestBody @Valid ClubCreateRequest request) {

        // 业务校验：社团名称是否已存在，如果存在则抛出业务异常
        Optional.ofNullable(clubService.getClubByClubName(request.getClubName()))
                .ifPresent(club -> {
                    throw new BusinessException(HttpStatusEnum.CONFLICT.getCode(), "社团创建失败：社团名称已存在。");
                });

        // 业务校验：创建人是否存在且未被逻辑删除，如果不存在则抛出业务异常
        Optional.ofNullable(userService.getById(request.getCreatorId()))
                .orElseThrow(() -> new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "社团创建失败：创建人用户不存在或已逻辑删除。"));

        Club club = new Club();
        BeanUtils.copyProperties(request, club);

        club.setCreateTime(LocalDateTime.now());
        club.setStatus(ClubStatusEnum.PENDING_REVIEW); // 默认新创建的社团状态为“待审核”

        boolean success = clubService.save(club);
        if (!success) { // 如果保存操作返回false但没有异常抛出
            throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "社团创建失败，请稍后重试。"); // 抛出业务异常
        }
        return ResponseResult.success(HttpStatusEnum.CREATED.getCode(), HttpStatusEnum.CREATED.getMessage(), club);
    }

    @Operation(summary = "更新社团信息", description = "根据社团ID更新社团信息")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "社团更新成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "404", description = "社团未找到"),
            @ApiResponse(responseCode = "409", description = "社团名称已存在"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PutMapping("/{id}")
    @PreAuthorize("hasRole('管理员')")
    public ResponseResult<Club> updateClub(
            @Parameter(description = "社团ID", required = true, example = "1") @PathVariable Long id,
            @Parameter(description = "更新后的社团对象", required = true) @RequestBody @Valid ClubUpdateRequest request) {

        Club existingClub = Optional.ofNullable(clubService.getById(id))
                .orElseThrow(() -> new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "社团未找到。"));

        // 校验更新的社团名称是否与其他社团冲突 (如果名称被修改且不为当前社团)
        Optional.ofNullable(request.getClubName())
                .filter(newName -> !newName.equals(existingClub.getClubName())) // 只有当名称实际改变时才校验
                .ifPresent(newName -> Optional.ofNullable(clubService.getClubByClubName(newName))
                        .filter(conflictClub -> !conflictClub.getClubId().equals(id)) // 确保不是自身
                        .ifPresent(conflictClub -> {
                            throw new BusinessException(HttpStatusEnum.CONFLICT.getCode(), "更新失败：社团名称已存在。");
                        }));

        // 如果更新中包含 creatorId，也需要校验创建人是否存在且未被逻辑删除
        Optional.ofNullable(request.getCreatorId())
                .filter(newCreatorId -> !newCreatorId.equals(existingClub.getCreatorId())) // 只有当 creatorId 实际改变时才校验
                .ifPresent(newCreatorId -> Optional.ofNullable(userService.getById(newCreatorId))
                        .orElseThrow(() -> new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "更新失败：新的创建人用户不存在或已逻辑删除。")));

        BeanUtils.copyProperties(request, existingClub);

        boolean success = clubService.updateById(existingClub);
        if (!success) { // 如果更新返回false
            throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "社团更新失败，请稍后重试。"); // 抛出业务异常
        }
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), existingClub);
    }

    @Operation(summary = "删除社团", description = "根据社团ID删除社团。")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "204", description = "社团删除成功"),
            @ApiResponse(responseCode = "404", description = "社团未找到"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('管理员')")
    public ResponseResult<Void> deleteClub(
            @Parameter(description = "社团ID", required = true, example = "1") @PathVariable Long id) {
        boolean success = clubService.removeById(id);
        if (!success) { // 如果删除返回false
            throw new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "社团未找到或删除失败。"); // 抛出业务异常
        }
        return ResponseResult.success(HttpStatusEnum.NO_CONTENT.getCode(), HttpStatusEnum.NO_CONTENT.getMessage(), null);
    }


    @Operation(summary = "根据社团名称获取社团", description = "根据社团名称获取社团详情，**包含创建人信息 (若创建人被逻辑删除则显示为未知)**，用于校验名称唯一性或查询单个社团")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功获取社团"),
            @ApiResponse(responseCode = "404", description = "社团未找到")
    })
    @GetMapping("/byName/{clubName}")
    public ResponseResult<ClubVo> getClubByClubName(
            @Parameter(description = "社团名称", required = true, example = "编程社") @PathVariable String clubName) {
        // 调用统一的搜索方法，只查一个，用于精确获取单个社团的详细VO
        ClubSearchRequest searchRequest = new ClubSearchRequest();
        searchRequest.setClubName(clubName);
        Page<ClubVo> page = new Page<>(1, 1);
        IPage<ClubVo> resultPage = clubService.searchClubsByConditions(page, searchRequest);

        // 使用Optional来提取结果并进行null检查
        return Optional.ofNullable(resultPage)
                .filter(p -> p.getRecords() != null && !p.getRecords().isEmpty())
                .map(p -> ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), p.getRecords().get(0)))
                .orElseThrow(() -> new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "社团未找到。")); // 抛出业务异常
    }

    @Operation(summary = "设置社团状态", description = "根据社团ID将社团状态设置为待审核、已批准或已拒绝")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "社团状态设置成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误或状态值无效"),
            @ApiResponse(responseCode = "404", description = "社团未找到"),
            @ApiResponse(responseCode = "500", description = "设置社团状态失败")
    })
    @PutMapping("/{id}/status/{newStatusStr}")
    @PreAuthorize("hasRole('管理员')")
    public ResponseResult<Void> setClubStatus(
            @Parameter(description = "社团ID", required = true, example = "1") @PathVariable Long id,
            @Parameter(description = "新的社团状态", required = true, example = "已批准", schema = @Schema(implementation = ClubStatusEnum.class))
            @PathVariable String newStatusStr) {

        boolean success = clubService.updateClubStatus(id, newStatusStr);
        if (!success) {
            // 如果 Service 返回 false，且社团不存在，则抛出 NOT_FOUND 业务异常
            Optional.ofNullable(clubService.getById(id))
                    .ifPresentOrElse(
                            existingClub -> { throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "设置社团状态失败：无效的状态值或内部错误。"); }, // 社团存在但更新失败
                            () -> { throw new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "社团未找到。"); } // 社团不存在
                    );
        }
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), "社团状态设置成功", null);
    }
}
